package sf.database.jdbc.type;

import javax.persistence.AttributeConverter;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 此类是为了对接{@link javax.persistence.AttributeConverter}接口
 * @param <X>
 * @param <Y>
 */
public class AttributeConverterType<X, Y> implements TypeHandler<X> {
    private AttributeConverter<X, Y> attributeConverter;
    private TypeHandler<Y> typeHandler;
    private Class<X> xclass;
    private Class<Y> yclass;
    private boolean mix;//控制是否需要走attributeConverter方法

    public AttributeConverterType() {

    }

    public AttributeConverterType(AttributeConverter<X, Y> attributeConverter, TypeHandler<Y> typeHandler, boolean mix) {
        this.attributeConverter = attributeConverter;
        this.typeHandler = typeHandler;
        this.mix = mix;
    }

    @Override
    public X get(ResultSet rs, String columnLabel) throws SQLException {
        Y y = typeHandler.get(rs, columnLabel);
        return toEntityValue(y);
    }

    @Override
    public X get(ResultSet rs, int columnIndex) throws SQLException {
        Y y = typeHandler.get(rs, columnIndex);
        return toEntityValue(y);
    }

    @Override
    public X get(CallableStatement cs, int parameterIndex) throws SQLException {
        Y y = typeHandler.get(cs, parameterIndex);
        return toEntityValue(y);
    }

    @Override
    public X get(CallableStatement cs, String parameterName) throws SQLException {
        Y y = typeHandler.get(cs, parameterName);
        return toEntityValue(y);
    }

    @Override
    public Object set(PreparedStatement ps, Object value, int index) throws SQLException {
        Y y = toDBValue(value);
        return typeHandler.set(ps, y, index);
    }

    @Override
    public Object set(CallableStatement cs, Object obj, String parameterName) throws SQLException {
        Y y = toDBValue(obj);
        return typeHandler.set(cs, y, parameterName);
    }

    @Override
    public void update(ResultSet rs, String columnLabel, Object value) throws SQLException {
        Y y = toDBValue(value);
        typeHandler.update(rs, columnLabel, y);
    }

    @Override
    public void update(ResultSet rs, int columnIndex, Object value) throws SQLException {
        Y y = toDBValue(value);
        typeHandler.update(rs, columnIndex, y);
    }

    protected X toEntityValue(Y y) {
        if (mix) {
            return attributeConverter.convertToEntityAttribute(y);
        } else {
            return (X) y;
        }
    }

    protected Y toDBValue(Object value) {
        if (mix) {
            return attributeConverter.convertToDatabaseColumn((X) value);
        } else {
            return (Y) value;
        }
    }

    @Override
    public Class<X> getDefaultJavaType() {
        return xclass;
    }

    @Override
    public int getSqlType() {
        return typeHandler.getSqlType();
    }

    public Class<X> getXclass() {
        return xclass;
    }

    public void setXclass(Class<X> xclass) {
        this.xclass = xclass;
    }

    public Class<Y> getYclass() {
        return yclass;
    }

    public void setYclass(Class<Y> yclass) {
        this.yclass = yclass;
    }

    public AttributeConverter<X, Y> getAttributeConverter() {
        return attributeConverter;
    }

    public void setAttributeConverter(AttributeConverter<X, Y> attributeConverter) {
        this.attributeConverter = attributeConverter;
    }

    public TypeHandler<Y> getTypeHandler() {
        return typeHandler;
    }

    public void setTypeHandler(TypeHandler<Y> typeHandler) {
        this.typeHandler = typeHandler;
    }

    public boolean isMix() {
        return mix;
    }

    public void setMix(boolean mix) {
        this.mix = mix;
    }
}
